using Microsoft.Extensions.Logging;
using SumerCoreDevOps.Infrastructure.Data;
using SumerCoreDevOps.Infrastructure.Tcp;
using SumerCoreDevOps.Shared.Enums;
using SumerCoreDevOps.Shared.Models.Messages;
using System.Collections.Concurrent;

namespace SumerCoreDevOps.Infrastructure.Artifacts;

/// <summary>
/// 产物代理下载服务（通过TCP从执行节点获取文件）
/// </summary>
public class ArtifactProxyDownloadService
{
    private readonly FreeSQLProvider _dbProvider;
    private readonly TcpServer _tcpServer;
    private readonly ILogger<ArtifactProxyDownloadService> _logger;

    // 存储等待的下载响应（ArtifactId -> 响应消息队列）
    private readonly ConcurrentDictionary<long, ConcurrentQueue<ArtifactDownloadResponseMessage>> _pendingDownloads = new();

    public ArtifactProxyDownloadService(
        FreeSQLProvider dbProvider,
        TcpServer tcpServer,
        ILogger<ArtifactProxyDownloadService> logger)
    {
        _dbProvider = dbProvider;
        _tcpServer = tcpServer;
        _logger = logger;
    }

    /// <summary>
    /// 处理来自执行节点的下载响应消息
    /// </summary>
    public void HandleDownloadResponse(ArtifactDownloadResponseMessage response)
    {
        var queue = _pendingDownloads.GetOrAdd(response.ArtifactId, _ => new ConcurrentQueue<ArtifactDownloadResponseMessage>());
        queue.Enqueue(response);
    }

    /// <summary>
    /// 通过TCP从执行节点下载产物文件
    /// </summary>
    public async Task<Stream?> DownloadArtifactAsync(long artifactId, CancellationToken cancellationToken = default)
    {
        try
        {
            // 查询产物信息
            var artifact = await _dbProvider.Orm
                .Select<Domain.Entities.BuildArtifact>()
                .Where(a => a.Id == artifactId && !a.IsDeleted)
                .FirstAsync(cancellationToken);

            if (artifact == null)
            {
                _logger.LogWarning("产物不存在: ArtifactId={ArtifactId}", artifactId);
                return null;
            }

            // 检查执行节点是否在线
            if (!_tcpServer.IsClientConnected(artifact.NodeId))
            {
                _logger.LogWarning("执行节点离线: NodeId={NodeId}, ArtifactId={ArtifactId}", artifact.NodeId, artifactId);
                return null;
            }

            _logger.LogInformation("开始从执行节点下载产物: ArtifactId={ArtifactId}, NodeId={NodeId}, FileSize={FileSize}",
                artifactId, artifact.NodeId, artifact.FileSize);

            // 创建响应队列
            var queue = _pendingDownloads.GetOrAdd(artifactId, _ => new ConcurrentQueue<ArtifactDownloadResponseMessage>());

            // 创建内存流来接收数据
            var memoryStream = new MemoryStream();
            int currentChunkIndex = 0;
            int totalChunks = -1;
            const int chunkSize = 1024 * 1024; // 1MB per chunk
            const int timeoutSeconds = 30;

            try
            {
                while (true)
                {
                    // 发送下载请求
                    var request = new ArtifactDownloadRequestMessage
                    {
                        ArtifactId = artifactId,
                        FilePath = artifact.FilePath,
                        ChunkIndex = currentChunkIndex,
                        ChunkSize = chunkSize
                    };

                    await _tcpServer.SendMessageAsync(artifact.NodeId, TcpMessageType.ArtifactDownloadRequest, request);

                    // 等待响应（带超时）
                    var timeout = DateTime.UtcNow.AddSeconds(timeoutSeconds);
                    ArtifactDownloadResponseMessage? response = null;

                    while (DateTime.UtcNow < timeout)
                    {
                        if (queue.TryDequeue(out response))
                        {
                            break;
                        }

                        await Task.Delay(100, cancellationToken);

                        if (cancellationToken.IsCancellationRequested)
                        {
                            _logger.LogWarning("产物下载被取消: ArtifactId={ArtifactId}", artifactId);
                            memoryStream.Dispose();
                            return null;
                        }
                    }

                    if (response == null)
                    {
                        _logger.LogError("等待产物分片响应超时: ArtifactId={ArtifactId}, ChunkIndex={ChunkIndex}",
                            artifactId, currentChunkIndex);
                        memoryStream.Dispose();
                        return null;
                    }

                    if (!response.Success)
                    {
                        _logger.LogError("产物分片下载失败: ArtifactId={ArtifactId}, Error={Error}",
                            artifactId, response.ErrorMessage);
                        memoryStream.Dispose();
                        return null;
                    }

                    // 解码并写入数据
                    if (!string.IsNullOrEmpty(response.FileDataBase64))
                    {
                        var data = Convert.FromBase64String(response.FileDataBase64);
                        await memoryStream.WriteAsync(data, 0, data.Length, cancellationToken);

                        _logger.LogDebug("已接收产物分片: ArtifactId={ArtifactId}, Chunk={ChunkIndex}/{TotalChunks}, Size={Size} bytes",
                            artifactId, response.ChunkIndex, response.TotalChunks, data.Length);
                    }

                    if (totalChunks < 0)
                    {
                        totalChunks = response.TotalChunks;
                    }

                    // 检查是否是最后一个分片
                    if (response.IsLastChunk || response.ChunkIndex >= totalChunks - 1)
                    {
                        _logger.LogInformation("产物下载完成: ArtifactId={ArtifactId}, TotalSize={Size} bytes",
                            artifactId, memoryStream.Length);
                        break;
                    }

                    currentChunkIndex++;
                }

                // 重置流位置以供读取
                memoryStream.Seek(0, SeekOrigin.Begin);
                return memoryStream;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "产物下载过程中发生错误: ArtifactId={ArtifactId}", artifactId);
                memoryStream.Dispose();
                throw;
            }
            finally
            {
                // 清理队列
                _pendingDownloads.TryRemove(artifactId, out _);
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "产物下载失败: ArtifactId={ArtifactId}", artifactId);
            return null;
        }
    }
}
